#ifndef _VECTOR_H_
#define _VECTOR_H_

#include <cmath>

struct vec3
{
	float x, y, z;

	// Constructor
	vec3() : x(0.f), y(0.f), z(0.f) { }
	vec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) { }

	// Math operators
	__forceinline vec3 operator+(const vec3& v) { return vec3(x + v.x, y + v.y, z + v.z); }
	__forceinline vec3 operator-(const vec3& v) { return vec3(x - v.x, y - v.y, z - v.z); }
	__forceinline float dot(const vec3& v) { return sqrtf(x * v.x + y * v.y + z * v.z); }
	__forceinline float operator*(const vec3& v) { return dot(v); }
	__forceinline vec3 cross(const vec3& v) { return vec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); }
	__forceinline vec3 operator^(const vec3& v) { return cross(v); }
	__forceinline vec3 operator*(const float& f) { return vec3(x * f, y * f, z * f); }
	__forceinline vec3 operator/(const float& f) { return vec3(x / f, y / f, z / f); }
	__forceinline vec3 operator-() { return vec3(-x, -y, -z); }

	__forceinline float lengthSq() const { return x * x + y * y + z * z; }
	__forceinline float length() const { return sqrtf(lengthSq()); }

	// Boolean operators
	__forceinline bool operator==(const vec3& v) { return x == v.x && y == v.y && z == v.z; }
	__forceinline bool operator!=(const vec3& v) { return !(*this == v); }
	__forceinline bool operator>(const vec3& v) { return lengthSq() > v.lengthSq(); }
	__forceinline bool operator<(const vec3& v) { return lengthSq() < v.lengthSq(); }
	__forceinline bool operator>=(const vec3& v) { return lengthSq() >= v.lengthSq(); }
	__forceinline bool operator<=(const vec3& v) { return lengthSq() <= v.lengthSq(); }

	// Normalize
	void Normalize() { float len = length(); x = x / len ; y = y / len; z = z / len; }
	vec3& Normalized() { return vec3(x, y, z).Normalize(); }
};
#endif // _VECTOR_H_